﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using FileManager_Client.BusinessLogic.FileManagerUserService;
using FileManager_Client.PresentationLayer.NewUi;
using FileManager_Client.Utility;
using FileManager_Client.Utility.CryptographyExtension;
using System.Linq;

namespace FileManager_Client.PresentationLayer.Common
{
    public static class UserLocalFile
    {
        #region Initialize
        private static UserLoginResult UserSession { get { return CacheGlobal.GetCache(GlobalString.System_Config_String.UserSession) as UserLoginResult; } }
        private static string UserLocalFilePath{get { return Path.Combine(Application.StartupPath, GlobalString.System_Config_String.UserLocalAppConfig); }}
        private static string SystemLocalFilePath { get { return Path.Combine(Application.StartupPath, GlobalString.System_Config_String.SystemLocalFilePath); } }
        private static string UserFolderPath { get { return Path.Combine(Application.StartupPath, UserSession.UserIdk__BackingField); } }
        private static string UserUploadingFileBreakPath { get { return Path.Combine(UserFolderPath, GlobalString.System_Config_String.UserUploadingBreakFile); } }
        private static string UserUploadLogFilePath { get { return Path.Combine(UserFolderPath, GlobalString.System_Config_String.UserUploadLogFile); } }
        private static string UserDownloadingBreakFilePath { get { return Path.Combine(UserFolderPath, GlobalString.System_Config_String.UserDownloadingBreakFile); } }
        private static string UserDownloadLogFilePath { get { return Path.Combine(UserFolderPath, GlobalString.System_Config_String.UserDownloadLogFile); } }
        private static readonly CustomSymmetricCryptography CustomSymmetricCryptography = new CustomSymmetricCryptography();
        public static void CheckUserFolder()
         {
            if (null == UserSession) return;
            if (!Directory.Exists(UserFolderPath))
                Directory.CreateDirectory(UserFolderPath);
         }
        public static void ClearUserLocalAppConfig()
        {
            if (File.Exists(UserLocalFilePath))
                File.Delete(UserLocalFilePath);
        }
        public static void SaveUserAppConfig(AutoLoginObject autoLoginObject)
        {
            try
            {
                if(!File.Exists(UserLocalFilePath))
                    File.Create(UserLocalFilePath).Close();
                var resultByte = ObjectToByteArray(autoLoginObject);
                var encrypto = CustomSymmetricCryptography.Encrypt(resultByte);
                File.WriteAllBytes(UserLocalFilePath, encrypto);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }

        }
        public static AutoLoginObject ReadUserAppConfig()
        {
            try
            {
                if (!File.Exists(UserLocalFilePath)) return null;
                var allbytes = File.ReadAllBytes(UserLocalFilePath);
                var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                var result = ByteArrayToObject(resultBytes) as AutoLoginObject;
                return result;
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
                File.WriteAllText(UserLocalFilePath,string.Empty);
                return null;
            }

        }
        private static object LockUploadingFile = new object();
        private static object LockUploadLogFile = new object();
        private static object LockDownloadingFile = new object();
        private static object LockDownloadLogFile = new object();
        #endregion

        #region System Config Save Local
        public static void SaveSystemConfig(SystemConfig systemConfig)
        {
            try
            {
                var resultByte = ObjectToByteArray(systemConfig);
                var encrypto = CustomSymmetricCryptography.Encrypt(resultByte);
                File.WriteAllBytes(SystemLocalFilePath, encrypto);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }

        }

        public static SystemConfig ReadSystemConfig()
        {
            try
            {
                if (!File.Exists(SystemLocalFilePath)) return null;
                var allbytes = File.ReadAllBytes(SystemLocalFilePath);
                var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                var result = ByteArrayToObject(resultBytes) as SystemConfig;
                return result;
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常",ex);
                File.WriteAllText(SystemLocalFilePath, string.Empty);
                return null;
            }

        }
        #endregion

        #region File Uploading Break Save Local
        public static void SaveFileUploadingBreakObject(FileUploadingBreakClass fileUploadingBreakClass)
        {
            try
            {
                lock (LockUploadingFile)
                {
                    if (!File.Exists(UserUploadingFileBreakPath))
                        File.Create(UserUploadingFileBreakPath).Close();
                    var allbytes = File.ReadAllBytes(UserUploadingFileBreakPath);
                    var result = new List<FileUploadingBreakClass>();
                    if(allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<FileUploadingBreakClass> ??
                                 new List<FileUploadingBreakClass>();
                    }
                    result.Add(fileUploadingBreakClass);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserUploadingFileBreakPath,encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        public static void RemoveFileUploadingBreakObject(string fileGuid)
        {
            try
            {
                lock (LockUploadingFile)
                {
                    if (!File.Exists(UserUploadingFileBreakPath))
                        File.Create(UserUploadingFileBreakPath).Close();
                    var allbytes = File.ReadAllBytes(UserUploadingFileBreakPath);
                    var result = new List<FileUploadingBreakClass>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<FileUploadingBreakClass> ??
                                 new List<FileUploadingBreakClass>();
                    }
                    var removeObj = result.FirstOrDefault(x => x.FileGuid.Equals(fileGuid));
                    if (null != removeObj) result.Remove(removeObj);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserUploadingFileBreakPath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        public static List<FileUploadingBreakClass> GetFileUploadingBreakObject()
        {
            try
            {
                lock (LockUploadingFile)
                {
                    if (!File.Exists(UserUploadingFileBreakPath))
                        File.Create(UserUploadingFileBreakPath).Close();
                    var allbytes = File.ReadAllBytes(UserUploadingFileBreakPath);
                    var result = new List<FileUploadingBreakClass>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<FileUploadingBreakClass> ??
                                 new List<FileUploadingBreakClass>();
                    }
                    return result;
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
                return null;
            }
        }
        #endregion

        #region File Upload Log Save Local
        public static List<UploadLogView> GetFileUploadLogObject()
        {
            try
            {
                lock (LockUploadLogFile)
                {
                    if (!File.Exists(UserUploadLogFilePath))
                        File.Create(UserUploadLogFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserUploadLogFilePath);
                    var result = new List<UploadLogView>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<UploadLogView> ??
                                 new List<UploadLogView>();
                    }
                    return result;
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
                return null;
            }
        }
        public static void RemoveFileUploadLogObject(string fileGuid)
        {
            try
            {
                lock (LockUploadLogFile)
                {
                    if (!File.Exists(UserUploadLogFilePath))
                        File.Create(UserUploadLogFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserUploadLogFilePath);
                    var result = new List<UploadLogView>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<UploadLogView> ??
                                 new List<UploadLogView>();
                    }
                    var removeObj = result.FirstOrDefault(x => x.FileGuid.Equals(fileGuid));
                    if (null != removeObj) result.Remove(removeObj);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserUploadLogFilePath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        public static void SaveFileUploadLogObject(UploadLogView uploadLogView)
        {
            try
            {
                lock (LockUploadLogFile)
                {
                    if (!File.Exists(UserUploadLogFilePath))
                        File.Create(UserUploadLogFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserUploadLogFilePath);
                    var result = new List<UploadLogView>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<UploadLogView> ??
                                 new List<UploadLogView>();
                    }
                    result.Add(uploadLogView);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserUploadLogFilePath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        #endregion

        #region File Downloading Break Save Local
        public static void SaveFileDownloadingBreakObject(FileDownloadingBreakClass fileDownloadingBreakClass)
        {
            try
            {
                lock (LockDownloadingFile)
                {
                    if (!File.Exists(UserDownloadingBreakFilePath))
                        File.Create(UserDownloadingBreakFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserDownloadingBreakFilePath);
                    var result = new List<FileDownloadingBreakClass>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<FileDownloadingBreakClass> ??
                                 new List<FileDownloadingBreakClass>();
                    }
                    result.Add(fileDownloadingBreakClass);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserDownloadingBreakFilePath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        public static void RemoveFileDownloadingBreakObject(string fileGuid)
        {
            try
            {
                lock (LockDownloadingFile)
                {
                    if (!File.Exists(UserDownloadingBreakFilePath))
                        File.Create(UserDownloadingBreakFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserDownloadingBreakFilePath);
                    var result = new List<FileDownloadingBreakClass>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<FileDownloadingBreakClass> ??
                                 new List<FileDownloadingBreakClass>();
                    }
                    var removeObj = result.FirstOrDefault(x => x.FileGuid.Equals(fileGuid));
                    if (null != removeObj) result.Remove(removeObj);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserDownloadingBreakFilePath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        public static List<FileDownloadingBreakClass> GetFileDownloadingBreakObject()
        {
            try
            {
                lock (LockDownloadingFile)
                {
                    if (!File.Exists(UserDownloadingBreakFilePath))
                        File.Create(UserDownloadingBreakFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserDownloadingBreakFilePath);
                    var result = new List<FileDownloadingBreakClass>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<FileDownloadingBreakClass> ??
                                 new List<FileDownloadingBreakClass>();
                    }
                    return result;
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
                return null;
            }
        }
        #endregion

        #region File Download Log Save Local
        public static List<DownloadLogView> GetFileDownloadLogObject()
        {
            try
            {
                lock (LockDownloadLogFile)
                {
                    if (!File.Exists(UserDownloadLogFilePath))
                        File.Create(UserDownloadLogFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserDownloadLogFilePath);
                    var result = new List<DownloadLogView>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<DownloadLogView> ??
                                 new List<DownloadLogView>();
                    }
                    return result;
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
                return null;
            }
        }
        public static void RemoveFileDownloadLogObject(string fileGuid)
        {
            try
            {
                lock (LockDownloadLogFile)
                {
                    if (!File.Exists(UserDownloadLogFilePath))
                        File.Create(UserDownloadLogFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserDownloadLogFilePath);
                    var result = new List<DownloadLogView>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<DownloadLogView> ??
                                 new List<DownloadLogView>();
                    }
                    var removeObj = result.FirstOrDefault(x => x.FileGuid.Equals(fileGuid));
                    if (null != removeObj) result.Remove(removeObj);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserDownloadLogFilePath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        public static void SaveFileDownloadLogObject(DownloadLogView uploadLogView)
        {
            try
            {
                lock (LockDownloadLogFile)
                {
                    if (!File.Exists(UserDownloadLogFilePath))
                        File.Create(UserDownloadLogFilePath).Close();
                    var allbytes = File.ReadAllBytes(UserDownloadLogFilePath);
                    var result = new List<DownloadLogView>();
                    if (allbytes.Length > 0)
                    {
                        var resultBytes = CustomSymmetricCryptography.Decrypt(allbytes);
                        result = ByteArrayToObject(resultBytes) as List<DownloadLogView> ??
                                 new List<DownloadLogView>();
                    }
                    result.Add(uploadLogView);
                    var saveByte = ObjectToByteArray(result);
                    var encrypto = CustomSymmetricCryptography.Encrypt(saveByte);
                    File.WriteAllBytes(UserDownloadLogFilePath, encrypto);
                }
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("写入本地文件异常", ex);
            }
        }
        #endregion

        // Convert an object to a byte array
        private static byte[] ObjectToByteArray(Object obj)
        {
            if (obj == null)
                return null;
            var bf = new BinaryFormatter();
            var ms = new MemoryStream();
            bf.Serialize(ms, obj);
            return ms.ToArray();
        }
        // Convert a byte array to an Object
        private static Object ByteArrayToObject(byte[] arrBytes)
        {
            var memStream = new MemoryStream();
            var binForm = new BinaryFormatter();
            memStream.Write(arrBytes, 0, arrBytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            var obj = binForm.Deserialize(memStream);
            return obj;
        }

    }

    [Serializable]
    public class AutoLoginObject
    {
        public string UserName { get; set; }
        public string PassWord { get; set; }
        public AutoLoginEnum AutoLogin { get; set; }
    }

    [Serializable]
    public class SystemConfig
    {
        public bool IsAutoStart { get; set; }
        public bool IsShowMessage { get; set; }
    }

      [Serializable]
    public enum AutoLoginEnum
    {
        RemeberPass = 0,
        AutoLogin = 1
    }
}